#include "MainPane.h"

#include <QMutex>
#include <QDateTime>
#include <QFile>
#include <QPushButton>
#include <QVBoxLayout>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <QHeaderView>
#include <QLabel>
#include <QLineEdit>
#include <QGroupBox>

#include <QApplication>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include <QDirIterator>
#include <QDir>

#include "QPubApi.h"


#include "VisionMainWnd.h"

QPlainTextEdit* _logTextEdit = nullptr;
QMutex mutex;
void outputLog(QtMsgType type, const QMessageLogContext& context, const QString& msg) {

	QDateTime curTime = QDateTime::currentDateTime();
	QString outMsg = curTime.toString("[yyyyMMdd-hh:mm:ss] ") + msg;

	bool fatal = false;
	QTextCharFormat fmt;	
	QColor textColor(0, 0, 0);
	switch (type)
	{
	case QtDebugMsg:
		fmt.setForeground(textColor);
		break;
	case QtInfoMsg:
		fmt.setForeground(textColor);
		break;
	case QtWarningMsg:
		fmt.setForeground(QColor(255, 100, 0));
		break;
	case QtCriticalMsg:
	case QtFatalMsg:
		fatal = true;
		fmt.setForeground(QColor(255, 0, 0));
		break;
	default:
		fmt.setForeground(textColor);
		break;
	}

	QMutexLocker locker(&mutex);
	if (_logTextEdit) {

		_logTextEdit->setCurrentCharFormat(fmt);
		_logTextEdit->appendPlainText(outMsg);

		if (fatal)
		{
			QFile criticalLog("log//critical_log.txt");
			criticalLog.open(QIODevice::WriteOnly | QIODevice::Append);
			QTextStream txtStream(&criticalLog);
			txtStream << outMsg << "\r\n";
			criticalLog.close();
		}
		else
		{
			QString appPath = QCoreApplication::applicationDirPath() + "//Log//";
			QString logName = appPath + curTime.toString("yyyy-MM") + ".txt";
			QFile outLog(logName);
			outLog.open(QIODevice::WriteOnly | QIODevice::Append);
			QTextStream txtStream(&outLog);
			txtStream << outMsg << "\r\n";
			outLog.close();
		}
	}
	locker.unlock();
}

MainPane::MainPane(QWidget* parent)
{
	mainWnd_ = (VisionMainWnd*)parent;

	initLayout();
}

MainPane::~MainPane()
{
	_logTextEdit = nullptr;
}

void MainPane::initLayout()
{
	// 1.料号信息
	QLabel* labPN = new QLabel("当前料号：",this);
	QLineEdit* editPN = new QLineEdit(this);
	editPN->setEnabled(false);
	//QComboBox* pnCombo = new QComboBox(this);
	QHBoxLayout* comboboxLyt = nullptr;
	QComboBox* pnCombo = QPubApi::createlineComboxComb("料号管理:", QStringList(), comboboxLyt, this);
	pnCombo->setObjectName("partNumComboBox");
	pnCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

	QHBoxLayout* pnLyt = new QHBoxLayout();
	pnLyt->addWidget(labPN);
	pnLyt->addWidget(editPN);
	labPN->setVisible(false);
	editPN->setVisible(false);

	// 添加lable显示模板图像
	QLabel* labModel = new QLabel(this);
	labModel->setAlignment(Qt::AlignCenter);
	modelLabel_ = labModel;
	

	// 2.本次识别目标坐标
	QLabel* labResult = new QLabel("识别结果:", this);
	QLineEdit* editResult = new QLineEdit(this);
	editResult->setObjectName("editResult");
	QHBoxLayout* rltLyt = new QHBoxLayout();
	rltLyt->addWidget(labResult);
	rltLyt->addWidget(editResult);

	// 3.所有识别结果：多个尾料
	QTableWidget* resultTab = new QTableWidget(this);
	resultTab->setObjectName("ShapeMatchTable");
	resultsTable_ = resultTab;
	initTableWidget(resultTab);

	// 4.统计信息
	QGroupBox* staGroupBox = new QGroupBox("统计信息", this);
	QLabel* labTotal = new QLabel("总数：", staGroupBox);
	QLineEdit* editTotal = new QLineEdit(staGroupBox);
	editTotal->setObjectName("totalCount");
	QPushButton* btnResetCount = new QPushButton("总数复位", staGroupBox);
	QHBoxLayout* statisticLyt = new QHBoxLayout();
	statisticLyt->addWidget(labTotal);
	statisticLyt->addWidget(editTotal);
	statisticLyt->addWidget(btnResetCount);
	staGroupBox->setLayout(statisticLyt);
	connect(btnResetCount, &QPushButton::clicked, [=] {
		auto insp = mainWnd_->getInspect();
		insp->resetObjCount();
		editTotal->setText("0");
		});

	// 5.日志标签
	QLabel* logTitle = new QLabel("系统日志",this);
	// 日志内容
	QPlainTextEdit* logWin = new QPlainTextEdit(this);
	logWin->setReadOnly(true);
	logWin->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
	logWin->setMinimumHeight(300);
	_logTextEdit = logWin;

	// 安装日志窗口
	qInstallMessageHandler(outputLog);

	QPushButton* clearLogsBtn = new QPushButton("清除日志");

	connect(clearLogsBtn, &QPushButton::clicked, this, [=] {
		logWin->clear();
		});

	QVBoxLayout* mainLayout = new QVBoxLayout();
	//mainLayout->addWidget(pnCombo);
	mainLayout->addLayout(comboboxLyt);
	mainLayout->addWidget(labModel);
	//mainLayout->addLayout(pnLyt);
	mainLayout->addLayout(rltLyt);
	mainLayout->addWidget(resultTab);
	mainLayout->addWidget(staGroupBox);
	mainLayout->addWidget(logTitle);
	mainLayout->addWidget(logWin);
	mainLayout->addWidget(clearLogsBtn);

	// 读取所有料号模板
	readModelsDir();	

	auto insp = mainWnd_->getInspect();
	connect(pnCombo, &QComboBox::currentIndexChanged, [=](int index)
		{
			auto pn = pnCombo->itemText(index);
			editPN->setText(pn);
			auto modelPath = QApplication::applicationDirPath() + "/model/" + pn + "/modelImage.png";
			QPixmap model(modelPath);
			labModel->setPixmap(model);
			insp->setCurrentPn(pn);
			insp->saveModelInfo();
			insp->loadModel(pn);
		});	

	setShowTableMatchResults(false);

	setLayout(mainLayout);
}

void MainPane::initTableWidget(QTableWidget* tab)
{
	tab->setEditTriggers(QAbstractItemView::NoEditTriggers);
	tab->setColumnCount(6);
	tab->setSelectionBehavior(QAbstractItemView::SelectRows);
	tab->setSelectionMode(QAbstractItemView::SingleSelection);
	tab->setObjectName("resultTab");

	QFont headerFont = tab->horizontalHeader()->font();
	headerFont.setBold(true);
	tab->horizontalHeader()->setFont(headerFont);

	//设置显示内容
	QStringList headerTitle;
	headerTitle << "ID" << "分数" << "行" << "列" << "角度" << "缩放";
	tab->setHorizontalHeaderLabels(headerTitle);
	int colsWidth[] = { 15,35,50,50,50,35 };
	for (int i = 0; i < 6; i++)
	{
		tab->setColumnWidth(i, colsWidth[i]);
	}
	tab->setFixedHeight(150);
}

void MainPane::ShowLogs()
{
	if (_logTextEdit->isVisible())
	{
		_logTextEdit->hide();
	}
	else
	{
		_logTextEdit->show();
	}
}

void MainPane::writeMatchObjResult(cv::Point2d objPos, double objAngle)
{
	auto edit = findChild<QLineEdit*>("editResult");
	QString str = QString("X:%0, Y:%1, rotAngle:%2").arg(objPos.x, 0, 'f', 1).arg(objPos.y, 0, 'f', 1).arg(int(objAngle));
	edit->setText(str);
}

void MainPane::writeAllResults(MatchResults* all)
{
	auto tab = findChild<QTableWidget*>("resultTab");
	tab->clearContents();
	tab->setRowCount(0);
	for (auto& r : *all)
	{
		int row = tab->rowCount();
		tab->insertRow(row);
		
		QString itemStr;
		QTableWidgetItem* item = new QTableWidgetItem();
		itemStr = QString::number(r.modelId);
		item->setText(itemStr);
		tab->setItem(row, 0, item);

		item = new QTableWidgetItem();
		itemStr = QString::number(r.score, 'f', 2);
		item->setText(itemStr);
		tab->setItem(row, 1, item);

		item = new QTableWidgetItem();
		itemStr = QString::number(r.x, 'f', 2);
		item->setText(itemStr);
		tab->setItem(row, 2, item);

		item = new QTableWidgetItem();
		itemStr = QString::number(r.y, 'f', 2);
		item->setText(itemStr);
		tab->setItem(row, 3, item);

		item = new QTableWidgetItem();
		itemStr = QString::number(r.rotAngle, 'f', 2);
		item->setText(itemStr);
		tab->setItem(row, 4, item);

		/*item = new QTableWidgetItem();
		itemStr = QString::number(r.y, 'f', 2);
		item->setText(itemStr);
		tab->setItem(row, 5, item);*/
	}
}

void MainPane::setShowTableMatchResults(bool show)
{
	resultsTable_->setHidden(!show);
}

void MainPane::showStatisticInfo()
{
	auto insp = mainWnd_->getInspect();
	long totalCount = insp->getObjCount();
	auto editTotalCount = findChild<QLineEdit*>("totalCount");
	editTotalCount->setText(QString::number(totalCount));
}

void MainPane::updateComboBox()
{
	QComboBox *pnCombo = findChild<QComboBox*>("partNumComboBox");
	int itemCount = pnCombo->count();
	auto insp = mainWnd_->getInspect();

	auto lastPn = insp->getCurPN();

	auto modelPath = QApplication::applicationDirPath() + "/model/" + lastPn + "/modelImage.png";
	QPixmap model(modelPath);
	modelLabel_->setPixmap(model);
	for (int i = 0; i < itemCount; i++)
	{
		if (pnCombo->itemText(i) == lastPn)
		{
			pnCombo->setCurrentIndex(i);
			break;
		}
	}
}

void MainPane::readModelConfig()
{
	QJsonDocument readAlg;
	QString strPath = QApplication::applicationDirPath() + "/model/models-info.json";
	QFile file(strPath);
	QByteArray jsonData;
	if (file.open(QIODevice::ReadOnly)) {
		jsonData = file.readAll();
		file.close();
	}
	QJsonParseError err_rpt;
	QJsonDocument jsonDocu = QJsonDocument::fromJson(jsonData, &err_rpt);
	if (jsonDocu.isObject())
	{
		auto rootObj = jsonDocu.object();
		auto partNumArry = rootObj["part_num"].toArray();
		
		int n = partNumArry.size();
		QStringList items;
		for (int i = 0; i < n; i++)
		{
			auto item = partNumArry.at(i).toString();
			items.push_back(item);
		}

		auto pnComb = findChild<QComboBox*>("partNumComboBox");
		pnComb->addItems(items);
	}
}


void MainPane::readModelsDir()
{
	QComboBox* pn = findChild<QComboBox*>("partNumComboBox");
	QString modelDir = QApplication::applicationDirPath() + "/model";
	QDirIterator it(modelDir, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
	//int index = 0;
	while (it.hasNext()) {
		it.next(); // 移动到下一个条目
		//qDebug() << it.fileName(); // 输出当前条目的名称
		pn->addItem(it.fileName());
		//index++;
	}
}
